

#include <stdio.h>
#include <stdlib.h>

#include "libH264Decoder.h"
#include <crtdbg.h>
// struct AVCodecContext *c;  // Codec Context
// struct AVFrame *picture;   // Frame	
		
// ================= MEMBER FUNCTIONS =======================
//

int FindStartCode (unsigned char *Buf, int zeros_in_startcode)
{
  int info;
  int i;

  info = 1;
  for (i = 0; i < zeros_in_startcode; i++)
    if(Buf[i] != 0)
      info = 0;

  if(Buf[i] != 1)
    info = 0;
  return info;
}

int getNextNal(FILE* inpf, unsigned char* Buf)
{
	int pos = 0;
	int StartCodeFound = 0;
	int info2 = 0;
	int info3 = 0;

	while(!feof(inpf) && (Buf[pos++]=fgetc(inpf))==0);

	while (!StartCodeFound)
	{
		if (feof (inpf))
		{
//			return -1;
			return pos-1;
		}
		Buf[pos++] = fgetc (inpf);
		info3 = FindStartCode(&Buf[pos-4], 3);
		if(info3 != 1)
			info2 = FindStartCode(&Buf[pos-3], 2);
		StartCodeFound = (info2 == 1 || info3 == 1);
	}
	fseek (inpf, -4, SEEK_CUR);
	return pos - 4;
}

// int main()
// {
// 	FILE * inpf=NULL;
// 	FILE * outf=NULL;
// 
// 	int i;
// 	int nalLen=0;
// 	unsigned char* Buf=NULL;
// 	int  got_picture, consumed_bytes; 	
// 
// 	inpf = fopen("test.264", "rb");
// 	outf = fopen("test.yuv", "wb");
// 
// 	if(!inpf)
// 		return -1;
// 
// 	Buf = (unsigned char*)calloc ( 3000000, sizeof(char));
// 
// //    dsputil_static_init();
//  
//     c = avcodec_alloc_context(); 
// 	if(!c)
// 		return -1;
// 
//     if (avcodec_open(c) < 0)
// 		return -1; 
// 	
//     picture   = avcodec_alloc_frame();
// 	if(!picture)
// 		return -1;
// 
// 	while(!feof(inpf))
// 	{		
// 		nalLen = getNextNal(inpf, Buf);
// 
// 		consumed_bytes= decode_frame(c, picture, &got_picture, Buf, nalLen); 
// 		
// 		if(consumed_bytes > 0)
// 		{
// //*
// 			for(i=0; i<c->height; i++)
// 				fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, outf);
// 			for(i=0; i<c->height/2; i++)
// 				fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, outf);
// 			for(i=0; i<c->height/2; i++)
// 				fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, outf);
// // */
// 		}
// 	}
// 
// 	if(inpf)
// 		fclose(inpf);
// 	
// 	if(outf)
// 		fclose(outf);
// 
// Decodereturn:
// 
// 	if(c)
// 	{
// 		avcodec_close(c); 
// 		av_free(c);
// 		c = NULL;
// 	} 
// 	if(picture)
// 	{
// 		av_free(picture);
// 		picture = NULL;
// 	}
// 
// 	if(Buf)
// 	{
// 		free(Buf);
// 		Buf = NULL;
// 	}    
// 
// 	return 0;		
// }

void initDecoder(AVCodecContext** c, AVFrame** picture)
{
	*c = avcodec_alloc_context(); 
	if(!(*c))
		return;

	if (avcodec_open(*c) < 0)
		return ; 

	*picture = avcodec_alloc_frame();
	if(!(*picture))
		return ;
}

void unInitDecoder(AVCodecContext**c, AVFrame**picture)
{
	if(*c)
	{
		avcodec_close(*c); 
		av_free(*c);
		*c = NULL;
	} 
	if(*picture)
	{
		av_free(*picture);
		*picture = NULL;
	}
}

void decodeNal(unsigned char* nalBuf, int nalLen, unsigned char* yuvBuf, AVCodecContext* c, AVFrame* picture)
{
	int i;
	int got_picture, consumed_bytes; 	

	
	consumed_bytes= decode_frame(c, picture, &got_picture, nalBuf, nalLen); 

	//_RPT3(_CRT_WARN, "%d %d %d\n", picture->linesize[0], picture->linesize[1], picture->linesize[2] );
	//printf("%d %d %d", picture->linesize[0], picture->linesize[1], picture->linesize[2]);

	if(consumed_bytes > 0)
	{
		//_RPT2(_CRT_WARN, "%d %d\n", consumed_bytes, c->height);

		for(i=0; i<c->height; i++)
			memcpy(yuvBuf+i*c->width, picture->data[0]+i*picture->linesize[0],c->width);
		for(i=0; i<c->height/2; i++)
			memcpy(yuvBuf+c->height*c->width+i*c->width/2, picture->data[1]+i*picture->linesize[1], c->width/2);
		for(i=0; i<c->height/2; i++)
			memcpy(yuvBuf+c->height*c->width+c->width/2*c->height/2+i*c->width/2, picture->data[2]+i*picture->linesize[2], c->width/2);
	}

	return ;		
}